#ifndef _WORLDENTITY_H_
#define _WORLDENTITY_H_

#include <GL/glfw.h>
#include "physics_calc.h"
#include "../../common/vector.h"
#include "../../common/utils.h"
#include "../gameplay/gameplay.h"

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <vector>

#define TYPE_PLAYER 1
#define TYPE_MAP_AREA 2
#define TYPE_PROJECTILE 3

#define SUBTYPE_WALL 1

#define PROJECTILE_BULLET 1

/* NOTA: i costruttori di copia sono necessari perche' la vector quando li aggiunge al vettore se li copia da quanto ho capito */

class GamePlay;
class PhysicsCalc;

class WorldEntity
{
	protected:
		/* accumulatore in cui vengono sommate tutte le forze che agiscono sull'entita',
		 * viene svuotato e ricalcolato ad ogni iterazione */
		Vector2D forceAccumulator;

	public:
		Vector2D velocity;
		int m_type;
		/* massa inversa, comoda per calcolare l'accelerazione (a = 1/m * F) 
		 * quindi massa 0 = massa infinita, oggetto che non si sposta
		 */
		GLfloat m_inverseMass;
		WorldEntity(void);
		WorldEntity(int t);
		WorldEntity(const WorldEntity &entity);
		~WorldEntity(void);
		
		/* svuota l'accumulatore delle forze */
		void clearAccumulator();
		/* aggiunge ua forza all'accumulatore */
		void addForce(Vector2D v);
		/* restituisce true se la massa e' 0 */
		bool hasFiniteMass();
		
		void getVelocity(Vector2D *v);
		
	friend class PhysicsCalc;
	friend class GFXEngine;
	//friend class WorldPlayer;
	
};

class WorldPlayer : public WorldEntity
{
	protected:
		
		GLfloat width, height; 
		GLfloat angle;
		GLfloat damping;
		
		Vector2D m_gravity;
		Vector2D acceleration;
		
		bool isJumping;
		
		char m_movement;
		
	public:
		GLfloat x, y;
		WorldPlayer(void);
		WorldPlayer(int t);
		WorldPlayer(const WorldPlayer &entity);
		~WorldPlayer(void);
		void setSize(GLfloat w, GLfloat h);
		void addAccel(Vector2D *accel);
		void integrate(double delta);
		void isMoving(char where);
		void stoppedMoving(char where);
		
	friend class GFXEngine;
	friend class CollisionDetector;
	friend class PhysicsCalc;
	friend class GamePlay;
};

class WorldArea : public WorldEntity
{
	protected:
		int numVertexs;
		GLfloat *vertexs;
		GLfloat color[3];
		
	public:
		WorldArea(void);
		~WorldArea(void);
		WorldArea(const WorldArea &entity);
		WorldArea(int num, GLfloat vtxs[], GLfloat color[3]);
		void init(int num, GLfloat vtxs[], GLfloat color[3]);
		void init(int num, std::vector<float> &vtxs, GLfloat r, GLfloat g, GLfloat b);
		
	friend class CollisionDetector;
	friend class GFXEngine;
	friend class PhysicsCalc;
	friend class Editor;

};

class WorldProjectile : public WorldEntity
{
	protected:
		int m_subtype;
		GLfloat x, y;
		GLfloat angle;
		GLfloat height, width;
		Vector2D velocity;
		Vector2D acceleration;
		Vector2D m_gravity;
		
		WorldPlayer *owner;
		
	public:
		WorldProjectile(void);
		~WorldProjectile(void);
		WorldProjectile(const WorldProjectile &entity);
		WorldProjectile(GLfloat x, GLfloat y, int subtype, Vector2D vel, Vector2D acc, Vector2D gravity);
		void integrate(double delta);
		void updateAngle(void);
		
	friend class GFXEngine;
	friend class World;
	friend class CollisionDetector;
};
#endif
